#include "link_list.h"
#include <stdlib.h>
void link_list_init(link_list *pl)
{
	pl->head = NULL;
}


void push_fornt(link_list *pl,void* data)
{
	list_node *newnode = malloc(sizeof(list_node));
	newnode->data  = data;
	newnode->pnext  = pl->head;
	pl->head = newnode;
}
list_node* forward(link_list *pl, unsigned n)
{
	unsigned i;
	list_node* cur;
	for(i = 0, cur = pl->head; cur != NULL && i<n; i++)
	{
		cur=cur->pnext;
	}
	return cur;
}
void list_foreach(link_list *pl,efun fun)
{
	int ret,i;
	list_node* cur;
	cur = pl->head;
	ret = 1;
	i = 0;
	while(ret&&cur)
	{
		ret = fun(i++,cur->data);
		cur = cur->pnext;
	}
}

void list_foreach_p(link_list* pl, efun_p fun, void* p)
{
	int ret, i;
	list_node* cur;
	cur = pl->head;
	ret = 1;
	i = 0;
	while (ret && cur)
	{
		ret = fun(i++, cur->data,p);
		cur = cur->pnext;
	}
}
void* remove_node(link_list *pl,unsigned n)
{
	unsigned i;
	list_node* cur, * per;
	void* data;
	data = NULL;

	if (!pl->head)return NULL;

	for (cur = pl->head, per = NULL, i = 0; cur != NULL && i < n; i++)
	{
		per = cur;
		cur = cur->pnext;
	}
	if (cur)
	{
		data = cur->data;
		if (per)
		{
			per->pnext = cur->pnext;
		}
		else
		{
			pl->head = cur->pnext;
		}
		free(cur);
	}
	
	return data;
}

void clear(link_list* pl, dfun fun)
{
	list_node* cur,*temp;
	cur = pl->head;
	while ( cur )
	{
		temp = cur;
		fun(cur->data);
		cur = cur->pnext;
		free(temp);
	}
	pl->head = NULL;
}

link_list filter_n(link_list* pl, filterfun fun)
{
	unsigned i;
	link_list l;
	list_node* cur;
	i = 0;
	link_list_init(&l);
	cur = pl->head;
	while (cur)
	{
		if (fun(i++, cur->data))
		{
			push_fornt(&l, cur->data);
		}
	}
	return l;
}

link_list filter_n_p(link_list* pl, filterfun_p fun, void* p)
{
	unsigned i;
	link_list l;
	list_node* cur;
	i = 0;
	link_list_init(&l);
	cur = pl->head;
	while (cur)
	{
		if (fun(i++, cur->data,p))
		{
			push_fornt(&l, cur->data);
		}
		cur = cur->pnext;
	}
	return l;
}

void filter(link_list* pl, filterfun fun)
{
	list_node* per,*cur,*temp;
	unsigned i;
	i = 0;
	per = NULL;
	cur = pl->head;
	while (cur)
	{
		if (! fun(i++, cur->data)) 
		{
			if (per)
			{
				per->pnext = cur->pnext;
			}
			else
			{
				pl->head = cur->pnext;
			}
			temp = cur;
		}else
		{
			per = cur;
			temp = NULL;
		}
		
		cur = cur->pnext;
		free(temp);
	}

}

void filter_p(link_list* pl, filterfun_p fun, void* p)
{
	list_node* per, * cur, * temp;
	unsigned i;
	i = 0;
	per = NULL;
	cur = pl->head;
	while (cur)
	{
		if (fun(i++, cur->data,p)==0)
		{
			if (per)
			{
				per->pnext = cur->pnext;
			}
			else
			{
				pl->head = cur->pnext;
			}
			temp = cur;
		}
		else
		{
			per = cur;
			temp = NULL;
		}

		cur = cur->pnext;
		free(temp);
	}
}

int is_empty(link_list* pl)
{
	return pl->head == NULL;
}

unsigned list_size(link_list* pl)
{
	list_node* cur;
	unsigned i = 0;
	cur = pl->head;
	while (cur)
	{
		i++;
		cur = cur->pnext;
	}

	return i;
}
